package com.springboot.ww.platform.tt.util;

import cn.hutool.core.date.DateUtil;
import com.springboot.ww.platform.tt.dto.TikTokTokenRes;
import com.ww.springboot.boot.utils.json.JsonUtil;
import lombok.extern.slf4j.Slf4j;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;

import static cn.hutool.core.util.ClassUtil.isSimpleValueType;

/**
 * 描述：
 *
 * @author 🧑 ‍wanwei
 * @since 2025-05-06 11:18
 */
@Slf4j
public class SignUtil {

    private static final char[] HEX_CHAR = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};

    private static String getUrl(String url, String host, TikTokTokenRes tokenRes) {
        return getUrl(url, host, tokenRes, new HashMap<>(), "");
    }

    public static String getUrl(String host, String url, TikTokTokenRes tokenRes, Map<String, Object> map, String req) {
        setParam(map, tokenRes, url, req);
        return host + url + getUrlParam(map);
    }

    public static String getUrl(String host, String url, TikTokTokenRes tokenRes, String req) {
        return getUrl(host, url, tokenRes, new HashMap<>(), req);
    }

    public static String getUrl(String host, String url, TikTokTokenRes tokenRes, Map<String, Object> map) {
        return getUrl(host, url, tokenRes, map, "");
    }

    public static void setParam(Map<String, Object> map, TikTokTokenRes tokenRes, String api, String req) {
        map.put("app_key", tokenRes.getAppKey());
        map.put("shop_cipher", tokenRes.getShopCipher());
        map.put("shop_id", tokenRes.getShopId());
        map.put("timestamp", DateUtil.currentSeconds());
        String appSecret = tokenRes.getAppSecret();
        map.put("sign", getSign(map, api, appSecret, req));
        map.put("access_token", tokenRes.getToken());
    }

    public static String getSign(Map<String, Object> map, String api, String appSecret, String req) {
        try {
            Set<String> set = map.keySet();
            TreeSet<String> treeSet = new TreeSet<>(set);
            // 生成要签名的字符串
            StringBuilder signText = new StringBuilder();
            signText.append(api);
            treeSet.forEach(key -> {
                signText.append(key);
                if (isSimpleValueType(map.get(key).getClass())) {
                    signText.append(map.get(key));
                } else {
                    signText.append(JsonUtil.toJson(map.get(key)));
                }
            });
            // 进行256加密
            String s = appSecret + signText + req + appSecret;
            Mac sha256Hmac = Mac.getInstance("HmacSHA256");
            SecretKeySpec secretKey = new SecretKeySpec(appSecret.getBytes(), "HmacSHA256");
            sha256Hmac.init(secretKey);
            byte[] bytes = sha256Hmac.doFinal(s.getBytes());
            // 转十六进制
            char[] buf = new char[bytes.length * 2];
            int index = 0;
            for (byte b : bytes) { // 利用位运算进行转换，可以看作方法一的变种
                buf[index++] = HEX_CHAR[b >>> 4 & 0xf];
                buf[index++] = HEX_CHAR[b & 0xf];
            }
            return new String(buf);
        } catch (Exception e) {
            log.error("tt sign失败!", e);
            throw new RuntimeException("tt sign失败!" + e.getMessage());
        }
    }

    public static String getUrlParam(Map<String, Object> authListMap) {
        StringBuilder urlText = new StringBuilder();
        urlText.append("?");
        authListMap.forEach((k, v) -> {
            urlText.append(k).append("=");
            if (isSimpleValueType(v.getClass())) {
                urlText.append(v);
            } else {
                urlText.append(JsonUtil.toJson(v));
            }
            ;
            urlText.append("&");
        });
        return urlText.substring(0, urlText.length() - 1);
    }
}
